# -*- coding=utf-8 -*-
# Author: junzew
# Date: 2017 May 27
# Adapted from code written by Alex I. Ramirez @alexram1313 arcompware.com

from pypinyin import lazy_pinyin
import pypinyin
import pydub
from pydub import AudioSegment
from pathlib import Path
import wave
#import pyaudio
#import time
import sys
import base64
import os
import requests
import atc
import argparse
import traceback
import time

# we shall forget about this key.
# shall we?
# make it standalone.
class TextToSpeech:
# now i just want the file, not to save it.
# could it be done?
    CHUNK = 1024
    punctuation = ['，', '。','？','！','“','”','；','：','（',"）",":",";",",",".","?","!","\"","\'","(",")"]

    def __init__(self):
        pass

    def speak_preprocess(self, text):
        syllables = lazy_pinyin(text, style=pypinyin.TONE3)
        print("debug:",syllables)
        delay = 0
        
        def preprocess(syllables):
            temp = []
            for syllable in syllables:
                for p in TextToSpeech.punctuation:
                    syllable = syllable.replace(p, "")
                if syllable.isdigit():
                    syllable = atc.num2chinese(syllable)
                    new_sounds = lazy_pinyin(syllable, style=pypinyin.TONE3)
                    for e in new_sounds:
                        temp.append(e)
                else:
                    temp.append(syllable)
            return temp

        syllables = preprocess(syllables)
        print("final output:",syllables)
        # here's the problem.

    def synthesize(self, text, dst, name, src="syllables/"):
        """
        Synthesize .wav from text
        src is the folder that contains all syllables .wav files
        dst is the destination folder to save the synthesized file
        """
        print("Synthesizing ...")
        delay = 0
        increment = 355 # milliseconds
        pause = 500 # pause for punctuation
        syllables = lazy_pinyin(text, style=pypinyin.TONE3)

        # initialize to be complete silence, each character takes up ~500ms
        result = AudioSegment.silent(duration=500*len(text))
        for syllable in syllables:
            path = src+syllable+".wav"
            sound_file = Path(path)
            # insert 500 ms silence for punctuation marks
            if syllable in TextToSpeech.punctuation:
                short_silence = AudioSegment.silent(duration=pause)
                result = result.overlay(short_silence, position=delay)
                delay += increment
                continue
            # skip sound file that doesn't exist
            if not sound_file.is_file():
                continue
            segment = AudioSegment.from_wav(path)
            result = result.overlay(segment, position=delay)
            delay += increment

        directory = dst
        if not os.path.exists(directory):
            os.makedirs(directory)

        result.export(directory+name+"__timestamp__"+str(time.time())+".wav", format="wav")
        print("Exported.")

if __name__ == '__main__':
    tts = TextToSpeech()
    
    parser = argparse.ArgumentParser(description="HanTTS: Chinese Text-to-Speech program")
    subparsers = parser.add_subparsers(title="subcommands", help='optional subcommands', dest='cmd')
    
    synthesize_parser = subparsers.add_parser('synthesize', help='synthesize audio from text')
    synthesize_parser.add_argument('--text', help='* (urllib.parse.quote_plus encoded) the text to convert to speech', dest='text')
    synthesize_parser.add_argument('--dst', help='* absolute destination directory for generated .wav file', dest='dst')
    synthesize_parser.add_argument('--src', help='absolute source directory for syllable .wav files (with / in the end)', dest='src')

    args = parser.parse_args()
    willexit = False
    name = None
    errors = []
    if args.cmd == 'synthesize':
        if not args.text:
            errors.append('ERROR: Missing argument --text')
            willexit=True
        if not args.src:
            args.src = None
        if not args.dst:
            errors.append('ERROR: Missing argument --dst')
            willexit=True
        if willexit:
            synthesize_parser.print_help()
            for x in errors:
                print(x)
            sys.exit(1)
        try:
            name = args.text
            args.text = base64.urlsafe_b64decode(args.text.encode()).decode()
        except:
            traceback.print_exc()
            sys.exit(1)
        assert args.dst.startswith("/")
        try:
            assert args.dst.endswith("/")
        except:
            args.dst+="/"
        assert os.path.isdir(args.dst)
        # will not make it for you.
        if args.src == None:
            tts.synthesize(args.text, args.dst, name)
        else:
            assert args.src.startswith("/")
            try:
                assert args.src.endswith("/")
            except:
                args.src+="/"
            assert os.path.isdir(args.src)
            tts.synthesize(args.text, args.dst, name, args.src)
    else:
        parser.print_help()
        sys.exit(1)
